<?php

namespace app\admin\controller\auth;

use app\admin\model\Admin as AdminModel;
use app\admin\model\AdminLog;
use app\common\controller\Backend;
use Exception;
use jueqi\Random;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\facade\Db;

/**
 * 角色管理
 */
class Admin extends Backend
{
    /**
     * 无需鉴权的方法
     */
    protected $noNeedPermission = ['changePassword', 'basicInfo'];
    /**
     * @var AdminModel
     */
    protected $model = null;
    /**
     * 新增/编辑时，对前端发送的字段进行排除（忽略不入库）
     * @var string[]
     */
    protected $preExcludeFields = ['id', 'create_time', 'update_time', 'password', 'salt', 'login_failure', 'last_login_time', 'last_login_ip'];

    /**
     * 快速搜索字段
     * @var string[]
     */
    protected $quickSearchField = ['username', 'nickname'];

    /**
     * 开启数据限制
     */
    protected $dataLimit = 'allAuthAndOthers';

    protected $dataLimitField = 'id';

    /**
     * 查看请求返回的主表字段控制
     */
    protected $indexField = ['id', 'username', 'nickname', 'email', 'mobile', 'status', 'create_time'];

    public function initialize()
    {
        parent::initialize();
        $this->model = new AdminModel();
    }

    /**
     * 查看
     */
    public function index()
    {
        try {
            // 剥去字符串中的HTML标签以及左右两边的空格
            $this->request->filter(['strip_tags', 'trim']);
            if (stringToBoolean($this->request->param('select'))) {
                // 下拉框数据接口
                $this->select();
            }
            // 生成搜索条件、排序等
            list($where, $alias, $limit, $order) = $this->queryBuilder();
            $res = $this->model
                ->field($this->indexField)
                ->withJoin($this->withJoinTable, $this->withJoinType)
                ->alias($alias)
                ->where($where)
                ->order($order)
                ->paginate($limit);

            $this->success('', [
                'list'   => $res->items(),
                'total'  => $res->total(),
                'remark' => get_route_remark(),
            ]);
        } catch (DbException $ex) {
            $this->success('', [
                'list'   => [],
                'total'  => 0,
                'remark' => get_route_remark(),
            ]);
        }
    }

    public function add()
    {
        // 判断是否是post请求
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (empty($data)) {
                $this->error('参数不能为空');
            }
            /**
             * 由于有密码字段-对方法进行重写
             * 数据验证
             */
            if ($this->modelValidate) {
                // 启用模型验证
                try {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate;
                        if ($this->modelSceneValidate) {
                            // 启用模型场景验证
                            $validate->scene('add');
                        }
                        $validate->check($data);
                    }
                } catch (ValidateException $e) {
                    $this->error($e->getMessage());
                }
            }

            $salt   = Random::build('alnum', 16); // 密码盐
            $passwd = encrypt_password($data['password'], $salt); // 加密密码

            $data   = $this->excludeFields($data); // 排除不需要入库的字段
            $result = false;
            if ($data['group_arr']) {
                // 验证分组权限
                $this->checkGroupAuth($data['group_arr']);
            }
            // 开启事务
            Db::startTrans();
            try {
                $data['salt']     = $salt;
                $data['password'] = $passwd;
                $result           = $this->model->save($data);
                if ($data['group_arr']) {
                    $groupAccess = [];
                    foreach ($data['group_arr'] as $datum) {
                        $groupAccess[] = [
                            'admin_id'    => $this->model->id, // 管理员ID
                            'group_id'    => $datum, // 分组ID
                            'create_time' => time(),
                        ];
                    }
                    // 批量添加管理权限分组信息
                    Db::name('admin_group_access')->insertAll($groupAccess);
                }
                // 提交事务
                Db::commit();
            } catch (Exception $e) {
                // 回滚
                Db::rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success('添加成功！');
            } else {
                $this->error('添加失败！');
            }
        }
        $this->error('请求异常');
    }

    /**
     * 验证分组权限
     * @param array $groups
     */
    public function checkGroupAuth(array $groups)
    {
        if ($this->auth->isSuperAdmin()) {
            return;
        }
        $authGroups = $this->auth->getAllAuthGroups('allAuthAndOthers');
        foreach ($groups as $group) {
            if (!in_array($group, $authGroups)) {
                $this->error('您没有权限向此分组添加管理员！');
            }
        }
    }

    /**
     * 修改
     * @param null $id
     */
    public function edit($id = null)
    {
        if (empty($id)) {
            $this->error('数据不存在');
        }
        try {
            // 查询管理员信息
            $row = $this->model->find($id);
        } catch (DataNotFoundException|ModelNotFoundException|DbException $ex) {
            $row = array();
        }
        if (empty($row)) {
            $this->error('数据不存在');
        }
        // 验证是否有该数据操作权限
        $dataLimitAdminIds = $this->getDataLimitAdminIds();
        if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
            $this->error('您没有此数据的操作权限');
        }
        // 判断是否是post请求
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (empty($data)) {
                $this->error('参数不能为空');
            }

            /**
             * 由于有密码字段-对方法进行重写
             * 数据验证
             */
            if ($this->modelValidate) {
                // 启用模型验证
                try {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate;
                        if ($this->modelSceneValidate) {
                            // 启用模型场景验证
                            $validate->scene('edit');
                        }
                        $validate->check($data);
                    }
                } catch (ValidateException $e) {
                    $this->error($e->getMessage());
                }
            }

            if ($this->auth->id == $data['id'] && $data['status'] == '0') {
                $this->error('请使用其他管理员帐户禁用当前帐户！');
            }

            if (isset($data['password']) && $data['password']) {
                // 重置管理员密码
                $this->model->resetPassword($data['id'], $data['password']);
            }

            $groupAccess = [];
            if ($data['group_arr']) {
                $checkGroups = [];
                foreach ($data['group_arr'] as $datum) {
                    if (!in_array($datum, $row->group_arr)) {
                        $checkGroups[] = $datum;
                    }
                    $groupAccess[] = [
                        'admin_id'    => $row->id, // 管理员ID
                        'group_id'    => $datum, // 分组ID
                        'create_time' => time(),
                    ];
                }
                // 验证分组权限
                $this->checkGroupAuth($checkGroups);
            }
            $data   = $this->excludeFields($data); // 排除不需要入库的字段
            $result = false;
            Db::startTrans(); // 开启事务
            try {
                // 删除管理权限分组信息
                Db::name('admin_group_access')->where('admin_id', $id)->delete();
                // 修改管理员信息
                $result = $row->save($data);
                // 批量添加管理权限分组信息
                if ($groupAccess) {
                    Db::name('admin_group_access')->insertAll($groupAccess);
                }
                Db::commit(); // 提交事务
            } catch (Exception $e) {
                Db::rollback(); // 回滚
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success('修改成功！');
            } else {
                $this->error('修改失败！');
            }
        }

        unset($row['salt'], $row['login_failure']);
        $row['password'] = '';
        $this->success('', [
            'row' => $row
        ]);
    }

    /**
     * 删除
     * @param null $ids
     */
    public function del($ids = null)
    {
        if (!$this->request->isDelete() || empty($ids)) {
            $this->error('请求异常或者参数错误！');
        }
        // 验证是否有该数据操作权限
        $dataLimitAdminIds = $this->getDataLimitAdminIds();
        if ($dataLimitAdminIds) {
            $this->model->where($this->dataLimitField, 'in', $dataLimitAdminIds);
        }
        $data = [];
        $pk   = $this->model->getPk(); // 获取主键
        try {
            // 批量查询数据
            $data = $this->model->field("id")->where($pk, 'in', $ids)->select();
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            $this->error($e->getMessage());
        }
        $count = 0; // 删除成功数量
        Db::startTrans(); // 开启事务
        try {
            foreach ($data as $v) {
                $count += $v->delete();
                Db::name('admin_group_access')
                    ->where('admin_id', $v['id'])
                    ->delete();
            }
            Db::commit(); // 提交事务
        } catch (Exception $e) {
            Db::rollback(); // 回滚
            $this->error($e->getMessage());
        }
        if ($count) {
            $this->success('删除成功！');
        } else {
            $this->error('删除失败！');
        }
    }

    /**
     * 修改管理员状态
     * @param null $id
     */
    public function editStatus($id = null)
    {
        if (empty($id)) {
            $this->error('数据不存在！');
        }
        try {
            // 查询数据
            $row = $this->model->find($id);
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            $row = array();
        }
        // 查询数据是否存在
        if (empty($row)) {
            $this->error('数据不存在！');
        }
        // 用户所在分组是否有权限修改
        $dataLimitAdminIds = $this->getDataLimitAdminIds();
        if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
            $this->error('您没有此数据的操作权限！');
        }

        // 判断是否post请求
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (empty($data)) {
                $this->error('参数不能为空！');
            }
            AdminLog::setTitle('修改状态');
            /**
             * 数据验证
             */
            if ($this->modelValidate) {
                // 启用模型验证
                try {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate;
                        if ($this->modelSceneValidate) {
                            // 启用模型场景验证
                            $validate->scene('editStatus');
                        }
                        $validate->check($data);
                    }
                } catch (ValidateException $e) {
                    $this->error($e->getMessage());
                }
            }

            if ($this->auth->id == $data['id'] && $data['status'] == '0') {
                $this->error('请使用其他管理员帐户禁用当前帐户！');
            }
            $result = false;
            Db::startTrans(); // 开始事务
            try {
                $result = $row->save($data); // 修改管理员状态
                Db::commit(); // 提交事务
            } catch (Exception $e) {
                Db::rollback(); // 回滚
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success('修改成功！');
            } else {
                $this->error('修改失败！');
            }
        } else {
            $this->error('请求异常！');
        }

    }

    /**
     * 修改密码
     * @return void
     */
    public function changePassword()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            $id   = $this->auth->id;
            if (empty($id)) {
                $this->error('数据不存在');
            }
            $oldPassword = $data['oldPassword'] ?? ''; // 登录密码
            $password    = $data['password'] ?? ''; // 新密码
            $rePassword  = $data['rePassword'] ?? ''; // 确认密码
            if (empty($oldPassword)) {
                $this->error('登录密码不能为空！');
            }
            if (empty($password)) {
                $this->error('新密码不能为空！');
            }
            if (empty($rePassword)) {
                $this->error('确认密码不能为空！');
            }
            if(mb_strlen($password) < 6 || mb_strlen($password) > 32){
                $this->error('新密码长度必须在6-32字符之间！');
            }
            if(mb_strlen($rePassword) < 6 || mb_strlen($password) > 32){
                $this->error('确认密码长度必须在6-32字符之间！');
            }
            if(!preg_match('/^(?!.*[&<>"\'\n\r]).{6,32}$/', $password)){
                $this->error('新密码包含特殊字符！');
            }
            if(!preg_match('/^(?!.*[&<>"\'\n\r]).{6,32}$/', $rePassword)){
                $this->error('确认密码包含特殊字符！');
            }
            try {
                // 查询管理员信息
                $field = "id,password,salt";
                $row   = $this->model->field($field)->find($id);
            } catch (DataNotFoundException|ModelNotFoundException|DbException $ex) {
                $row = array();
            }
            if (empty($row)) {
                $this->error('数据不存在');
            }
            if (encrypt_password($password, $row->salt) != encrypt_password($rePassword, $row->salt)) {
                $this->error('两次密码输入不一致！');
            }
            if ($row->password != encrypt_password($oldPassword, $row->salt)) {
                $this->error('登录密码错误！');
            }
            if($row->password == encrypt_password($password, $row->salt)){
                $this->error('新密码与当前密码一致！');
            }
            $data   = $this->excludeFields($data); // 排除不需要入库的字段
            $result = false;
            Db::startTrans(); // 开启事务
            try {
                $data['password'] = encrypt_password($password, $row->salt);
                // 修改管理员信息
                $result = $row->save($data);
                Db::commit(); // 提交事务
            } catch (Exception $e) {
                Db::rollback(); // 回滚
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success('修改成功！');
            } else {
                $this->error('修改失败！');
            }
        }
        $this->error('修改失败！');
    }

    /**
     * 基本资料
     * @return void
     */
    public function basicInfo()
    {
        $id = $this->auth->id;
        if (empty($id)) {
            $this->error('数据不存在');
        }
        try {
            // 查询管理员信息
            $field = "id,username,nickname,name,email,mobile";
            $row   = $this->model->field($field)->find($id);
        } catch (DataNotFoundException|ModelNotFoundException|DbException $ex) {
            $row = array();
        }
        if (empty($row)) {
            $this->error('数据不存在');
        }
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (empty($data)) {
                $this->error('参数不能为空');
            }
            /**
             * 由于有密码字段-对方法进行重写
             * 数据验证
             */
            if ($this->modelValidate) {
                // 启用模型验证
                try {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate;
                        if ($this->modelSceneValidate) {
                            // 启用模型场景验证
                            $validate->scene('basicInfo');
                        }
                        $validate->check($data);
                    }
                } catch (ValidateException $e) {
                    $this->error($e->getMessage());
                }
            }
            $data   = $this->excludeFields($data); // 排除不需要入库的字段
            $result = false;
            Db::startTrans(); // 开启事务
            try {
                // 修改管理员信息
                $result = $row->save($data);
                Db::commit(); // 提交事务
            } catch (Exception $e) {
                Db::rollback(); // 回滚
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success('修改成功！');
            } else {
                $this->error('修改失败！');
            }
        }
        $this->success('', [
            'row' => $row->getData()
        ]);
    }

}
